package org.example.lysh.service.impl;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.netty.channel.Channel;
import org.example.lysh.common.po.User;
import org.example.lysh.mapper.UserMapper;
import org.example.lysh.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author liyishan
 * @date 2023/7/14 14:30
 * @apiNote
 */
@Service
public class LoginServiceImpl implements LoginService {

    private static final Duration EXPIRE_TIME = Duration.ofHours(1);

    private static final Long MAX_MUM_SIZE = 10000L;

    private static final AtomicInteger CODE = new AtomicInteger();


    /**
     * 所有请求登录的code与channel关系
     */
    private static final Cache<Integer, Channel> WAIT_LOGIN_MAP = Caffeine.newBuilder()
            .expireAfterWrite(EXPIRE_TIME)
            .maximumSize(MAX_MUM_SIZE)
            .build();
    @Autowired
    private UserMapper userMapper;

    /**
     * 处理用户登录请求，需要返回一张带code的二维码
     *
     * @param channel
     */
    /*@SneakyThrows
    @Override
    //todo  频率注解
    //@FrequencyControl(time = 100, count = 5, spEl = "T(com.abin.mallchat.common.common.utils.RequestHolder).get().getIp()")
    public void handleLoginReq(Channel channel) {
        //生成随机不重复的登录码
        Integer code = generateLoginCode(channel);
        //请求微信接口，获取登录码地址
        WxMpQrCodeTicket wxMpQrCodeTicket = wxMpService.getQrcodeService().qrCodeCreateTmpTicket(code, (int) EXPIRE_TIME.getSeconds());
        //返回给前端
        sendMsg(channel, WSAdapter.buildLoginResp(wxMpQrCodeTicket));
    }*/

    /**
     * 获取不重复的登录的code，微信要求最大不超过int的存储极限
     * 防止并发，可以给方法加上synchronize，也可以使用cas乐观锁
     *
     * @return
     */
    private Integer generateLoginCode(Channel channel) {
        do {
            CODE.getAndIncrement();
        } while (WAIT_LOGIN_MAP.asMap().containsKey(CODE.get())
                || Objects.isNull(WAIT_LOGIN_MAP.get(CODE.get(), c -> channel)));
        return CODE.get();
    }
    @Override
    public void login(Long userId) {
        User user= userMapper.selectById(userId);

    }
}
